package com.inforim.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.security.auth.login.LoginException;

import com.cognos.developer.schemas.bibus._3.BaseClass;
import com.cognos.developer.schemas.bibus._3.BooleanProp;
import com.cognos.developer.schemas.bibus._3.ContentManagerServiceStub;
import com.cognos.developer.schemas.bibus._3.Group;
import com.cognos.developer.schemas.bibus._3.Policy;
import com.cognos.developer.schemas.bibus._3.PropEnum;
import com.cognos.developer.schemas.bibus._3.QueryOptions;
import com.cognos.developer.schemas.bibus._3.Role;
import com.cognos.developer.schemas.bibus._3.SearchPathMultipleObject;
import com.cognos.developer.schemas.bibus._3.Sort;
import com.inforim.cognos.CognosClient;
import com.inforim.cognos.utils.CognosHelper;
import com.inforim.module.CSVObject;
import com.inforim.module.CogAccount;
import com.inforim.module.CogObject;
import com.inforim.module.CogRole;

public class CSVAuthMember {
	
	public Map<String, CogRole> authCache = new HashMap<String, CogRole>();
	public Map<String, CogAccount> accountCache = new HashMap<String, CogAccount>();
	public List<CogObject> folders = new ArrayList<CogObject>();
	public List<CogObject> packages = new ArrayList<CogObject>();
	
	public CSVObject getSecurityObject(CognosClient client,String searchPath) {
		ContentManagerServiceStub cmServiceStub = (ContentManagerServiceStub) client
				.getService("ContentManagerService");
		CSVObject csvObject = new CSVObject();
		CogRole cogRole;
		System.out.println("Loading SecurityObject searchPath:"+searchPath);
		if(authCache.containsKey(searchPath)){
			cogRole=authCache.get(searchPath);
		}else{
			cogRole=getUserFromRole(cmServiceStub, searchPath);
			authCache.put(searchPath, cogRole);
		}
		csvObject.addCogRole(cogRole);
		return csvObject;
	}
	public CSVObject getRolePerFromCogObj(CognosClient client,CogObject cogObject) {
		CSVObject csvObject = new CSVObject();
		String obj_searchpath=cogObject.getPath();
		csvObject.setCogObject(cogObject);
		
		BaseClass[] results = new BaseClass[0];
		ContentManagerServiceStub cmServiceStub = (ContentManagerServiceStub) client
				.getService("ContentManagerService");
		try {
			results = cmServiceStub.query(new SearchPathMultipleObject(
					obj_searchpath), new PropEnum[] { PropEnum.searchPath,
					PropEnum.policies }, new Sort[0], new QueryOptions());
			System.out.println(obj_searchpath+" has been loaded!");
		} catch (RemoteException remoteEx) {
			System.out.println("Caught Remote Exception:\n");
			remoteEx.printStackTrace();
		}

		for (int i = 0; i < results[0].getPolicies().getValue().length; ++i) {
			Policy pol = results[0].getPolicies().getValue()[i];
			String searchPath=pol.getSecurityObject().getSearchPath().getValue();
			CogRole cogRole;
			System.out.println("Loading SecurityObject searchPath:"+searchPath);
			if(authCache.containsKey(searchPath)){
				cogRole=authCache.get(searchPath);
			}else{
				cogRole=getUserFromRole(cmServiceStub, searchPath);
				authCache.put(pol.getSecurityObject().getSearchPath().getValue(), cogRole);
			}
			csvObject.addCogRole(cogRole);
			System.out.println("Loading SecurityObject finished searchPath:"+searchPath);
		}
		
		return csvObject;
	}
	
	public CogRole getUserFromRole(ContentManagerServiceStub cmServiceStub,
			String rolesearchpath) {
		CogRole cogRole=new CogRole();
		
		PropEnum[] props = { PropEnum.searchPath, PropEnum.defaultName,
				PropEnum.members };
		if (cmServiceStub != null) {
			Sort[] sortArray = { new Sort() };
			try {
				BaseClass[] bc = cmServiceStub.query(
						new SearchPathMultipleObject(rolesearchpath), props,
						sortArray, new QueryOptions());
				if (bc == null)
					System.out
							.println("\n\nError occurred in function viewAll.");
				if (bc.length <= 0) {
					System.out.println("There are currently no user.");
				}
				cogRole = getAccount(bc, cmServiceStub,cogRole);

			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return cogRole;
	}
	private boolean isCognosRole(String searchPath){
		boolean result=true;
		int begin=searchPath.indexOf("(\"")+"(\"".length();
		int end=searchPath.indexOf(":");
		String nameSpace=searchPath.substring(begin,end);
		if(nameSpace.length()>0)result=false;
		return result;
		
	}
	private CogRole getAccount(BaseClass[] bc,
			ContentManagerServiceStub cmServiceStub,CogRole cogRole) throws RemoteException {

		Sort[] sortArray = { new Sort() };
		PropEnum[] props = { PropEnum.searchPath, PropEnum.defaultName,
				PropEnum.members };

		BaseClass[] bcchildren = new BaseClass[1];
		for (int i = 0; (bc != null) && (i < bc.length); ++i) {
			if (bc[i] instanceof Role) {
				String name=((Role)bc[i]).getDefaultName().getValue();
				bcchildren = ((Role) bc[i]).getMembers().getValue();
//				if(((Role)bc[i]).getSearchPath().getValue().indexOf("SED")>0){
				if(!isCognosRole(((Role)bc[i]).getSearchPath().getValue())){
					cogRole.setSedName(name);
				}else {
					cogRole.setCogName(cogRole.getCogName()+(cogRole.getCogName().equals("")?"":"->")+name);
				}
				System.out.println("Loading Role:"+name);
				cogRole=getAccount(bcchildren, cmServiceStub,cogRole);
			} else if (bc[i] instanceof Group) {
				if(((Group)bc[i]).getDefaultName()!=null){
					String name=((Group)bc[i]).getDefaultName().getValue();
//					if(((Group)bc[i]).getSearchPath().getValue().indexOf("SED")>0){
					if(!isCognosRole(((Group)bc[i]).getSearchPath().getValue())){
						cogRole.setSedName(name);
					}else{
						cogRole.setCogName(cogRole.getCogName()+(cogRole.getCogName().equals("")?"":"->")+name);
					}
					bcchildren = ((Group) bc[i]).getMembers().getValue();
					System.out.println("Loading Role:"+name);
				}else{
					bcchildren = cmServiceStub.query(
							new SearchPathMultipleObject(bc[i].getSearchPath()
									.getValue()), props, sortArray,
							new QueryOptions());
					
				}
				cogRole=getAccount(bcchildren, cmServiceStub,cogRole);
			} else {
				bcchildren[0] = bc[i];
				CogAccount cogAccount=new CogAccount();
				if(accountCache.containsKey(bc[i].getSearchPath().getValue())){
					cogAccount=accountCache.get(bc[i].getSearchPath().getValue());
				}else{
					BaseClass[] bcuser = cmServiceStub.query(
							new SearchPathMultipleObject(bc[i].getSearchPath()
									.getValue()), props, sortArray,
							new QueryOptions());

					String mudid = bcuser[0].getSearchPath().getValue();
					int uid = mudid.indexOf("uid=");
					boolean has_mudid = false;
					if (mudid != null && uid >= 0) {
						mudid = mudid.substring(uid);
						int index1 = mudid.indexOf(",");
						int index2 = mudid.indexOf(")");
						mudid = mudid.substring("uid=".length(),
								Math.min(index1, index2));
						has_mudid = true;
					}
					String emailName = bcuser[0].getDefaultName().getValue();
					cogAccount.setName(emailName);
					if (has_mudid) {
						// emailName=mudid;
						cogAccount.setMudid(mudid);
					}
					accountCache.put(bc[i].getSearchPath().getValue(), cogAccount);
				}
				cogRole.addCogAccount(cogAccount);
					
			}
			
		}
		
		return cogRole;
	}
	//iterator folder & package
	public void getChildrenFolder(CognosClient cognosClient, String searchPath) {
		ContentManagerServiceStub cmServiceStub = (ContentManagerServiceStub) cognosClient
				.getService("ContentManagerService");
		PropEnum[] props = { PropEnum.searchPath, PropEnum.defaultName,
				PropEnum.members,PropEnum.disabled };
		Sort[] sortArray = { new Sort() };
		BaseClass[] folderes = null;
		BaseClass[] pkgs = null;
		try {
			folderes = cmServiceStub.query(new SearchPathMultipleObject(
					searchPath + "/folder"), props, sortArray,
					new QueryOptions());
			pkgs = cmServiceStub.query(new SearchPathMultipleObject(searchPath
					+ "/package"), props, sortArray, new QueryOptions());
			for (BaseClass folder : folderes) {
				if (folder.getSearchPath().getValue()
						.equals("/content/folder[@name='Samples']")
						|| folder
								.getSearchPath()
								.getValue()
								.equals("/content/folder[@name='Samples_PowerCube']"))
					continue;
				if(!folder.getSearchPath().getValue()
				.equals("/content/folder[@name='Model']")){
					CogObject cogObject=new CogObject();
					cogObject.setPath(folder.getSearchPath().getValue());
					cogObject.setType("folder");
					cogObject.setDisabled(folder.getDisabled().isValue());
					folders.add(cogObject);
				}
				getChildrenFolder(cognosClient, folder.getSearchPath()
						.getValue());

			}
			for (BaseClass pkg : pkgs) {
				CogObject cogObject=new CogObject();
				cogObject.setPath(pkg.getSearchPath().getValue());
				cogObject.setType("package");
//				BooleanProp isDisabled=pkg.getDisabled();
//				if(isDisabled.){
//					System.out.println(pkg.getDisabled().isValue());
//				}
				cogObject.setDisabled(pkg.getDisabled().isValue());
				packages.add(cogObject);
				getChildrenFolder(cognosClient, pkg.getSearchPath().getValue());
			}
			System.out.println("Finished initialized folders & packages");
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//iterator folder & package
	public BaseClass[] getChildrenAsType(CognosClient cognosClient, String searchPath,String type) {
		ContentManagerServiceStub cmServiceStub = (ContentManagerServiceStub) cognosClient
				.getService("ContentManagerService");
		PropEnum[] props = { PropEnum.searchPath, PropEnum.defaultName,
				PropEnum.members,PropEnum.disabled };
		Sort[] sortArray = { new Sort() };
		BaseClass[] result = null;
		try {
			result = cmServiceStub.query(new SearchPathMultipleObject(
					searchPath + "/"+type), props, sortArray,
					new QueryOptions());
			
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	public static void main(String[] args) {
		String dispatchUrl="";
		String userName="";
		String password="";
		String nameSpace="";
		String path="";
		for(int i=0;i<args.length;i++){
			String param=args[i];
			if(param.startsWith("-dispatchUrl=")){
				dispatchUrl=param.replaceAll("-dispatchUrl=", "");
			}
			if(param.startsWith("-userName=")){
				userName=param.replaceAll("-userName=", "");
			}
			if(param.startsWith("-password=")){
				password=param.replaceAll("-password=", "");
				try {
					DESUtil desUtil = new DESUtil();
					password = desUtil.decrypt(password);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(param.startsWith("-nameSpace=")){
				nameSpace=param.replaceAll("-nameSpace=", "");
			}
			if(param.startsWith("-path=")){
				path=param.replaceAll("-path=", "");
			}
		}
		
		//login
		CognosClient cognosClient = CognosHelper.getClient();
		cognosClient.setDispatch(dispatchUrl);
		cognosClient.setUsername(userName);
		cognosClient.setPassword(password);
		cognosClient.setNamespace(nameSpace);
		try {
			cognosClient.logon();
			System.out.println("logon Cognos success!");
		} catch (LoginException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out
					.println("Connect to Cognos failed, please check username & pasword in config.xml or Cognos enviroment.");
			return;
		}

		CSVAuthMember cam = new CSVAuthMember();
		System.out.println("Initializing folders & package");
		cam.getChildrenFolder(cognosClient, "/content");
		String output = "\"PATH\",\"DISABLED\",\"COGNOSROLE\",\""+nameSpace+"ROLE\",\"NAME\",\"MUDID\"\r\n";
		for (int i = 0; i < cam.folders.size(); i++) {
			CogObject folder = cam.folders.get(i);
			output += cam.getRolePerFromCogObj(cognosClient, folder).toString();
			System.out.println("Folder["+i+"]"+" has excuted!");
		}
		File file = new File(path+File.separator+"authList_Folder.csv");
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file);
			fos.write(new byte[]{(byte)0xEF,(byte)0xBB,(byte)0xBF});
			fos.write(output.getBytes("UTF-8"));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			fos.close();
			System.out.println(file.getAbsolutePath()+" has created!");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
//		output = "=========PACKAGES=========\r\n";
		output = "\"PATH\",\"DISABLED\",\"COGNOSROLE\",\""+nameSpace+"ROLE\",\"NAME\",\"MUDID\"\r\n";
		for (int i = 0; i < cam.packages.size(); i++) {
			CogObject pkg = cam.packages.get(i);
			output += cam.getRolePerFromCogObj(cognosClient, pkg).toString();
			System.out.println("Package["+i+"]"+" has excuted!");
		}
		
		file = new File(path+File.separator+"authList_Package.csv");
		try {
			fos = new FileOutputStream(file);
			fos.write(new byte[]{(byte)0xEF,(byte)0xBB,(byte)0xBF});
			fos.write(output.getBytes("UTF-8"));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			fos.close();
			System.out.println(file.getAbsolutePath()+" has created!");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
//		output = "\"\",\"COGNOSROLE\",\""+nameSpace+"ROLE\",\"NAME\",\"MUDID\"\r\n";
//		output +=cam.getSecurityObject(cognosClient,"CAMID(\":分析用户\")").toString(); //没有用到的角色
//		file = new File(path+File.separator+"authList_Role.csv");
//		try {
//			fos = new FileOutputStream(file);
//			fos.write(new byte[]{(byte)0xEF,(byte)0xBB,(byte)0xBF});
//			fos.write(output.getBytes("UTF-8"));
//		} catch (FileNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		try {
//			fos.close();
//			System.out.println(file.getAbsolutePath()+" has created!");
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
	}
}
